iT邦幫忙

DAY 16
7

程式設計心法系列 第 16

程式設計心法:15.流程控制--迴圈

  • 分享至 

  • xImage
  •  

迴圈也是程設設計中不可或缺的 statement,寫程式很多時候就是要幫我們做掉一些重複無意義的動作(可是偏偏很多 User 喜歡做這些事情...XD),從 for-loop,while-loop, do-until...每一種語言都有自己的迴圈控制器,不過寫法大同小異。

最怕也最常發生的就是,產生無窮迴圈。例如:

do while not rs.eof
  a=rs.fields(0).value
loop

少寫了一個 rs.movenext() 結果程式進入無窮迴圈,只好 CTRL+ALT+DEL。可以 break 掉的還好,最怕是 run 在 console 的程式,一 run 的結果,整個 server 都 hang 住,那就糗大了!還好 VB.Net 改採 Data Reader 的方式,

do while dr.read()
  ...
loop

這樣就不會有無窮迴圈問題的發生,當然這只是一種情況,還有很多因為變數的控制問題,導致迴圈運作不正常。所以,以下就介紹幾個寫迴圈時,該注意的地方。
.將初始化的程式碼放在靠近迴圈的地方
將初始化的動作放在迴圈的起始處集中處理,對程式維護與閱讀上會比較方便,也不會漏掉修改而導致錯誤產生。

.保持迴圈的完整結構
有時候為了節省程式碼,可能一行的指令就可以執行完一個迴圈的動作,如:while(!rs.eof) i++; 也許寫起來很方便,但是常會造成程式撰寫時判斷上的錯誤,所以還是將完整的迴圈結構寫好,反正也不會影響執行的效率,又可避免掉可能發生錯誤的風險,何樂而不為?

.避免空迴圈
寫 console 程式時,可能需要等待按鍵而採用空迴圈讓程式 waiting,如:

while ( (InputChar = getch()) != '\n' );

這樣對程式的閱讀上,比較不好懂,如果改寫成以下情況

do
  InputChar = getch();
while ( InputChar != '\n' )

這樣就會比較好辨識,程式所要做的事情。

.避免依賴迴圈變數結束後的值
很多時候,我們常會使用迴圈執行後的變數值,例如 for i=1 to n,我們在後面會認為迴圈執行完後的值為 n+1,所以就直接拿 i 來使用。可是錯誤也常會出現在這邊,如果程式中有離開迴圈的情況,這樣就可能與我們之前所設想的情況會不一樣,而導致錯誤。
如書中的例子:

for (i=0;i<MaxRecords;i++)
{
  if (Entry[i]==TestValue)
  {
    break;
  }
}
if (i<MaxRecords)
  return (TRUE);
else
  return (FALSE);

我們無從判定目前的 i 的值會是多少,所以導致回傳的值可能會出現錯誤,如果改成

Found=FALSE;
for (i=0;i<MaxRecords;i++)
{
  if (Entry[i]==TestValue)
  {
    Found=TRUE;
    break;
  }
}
return (Found);

這樣是不是就清楚許多!

.使用安全計數器
使用安全計數是避免無窮迴圈導致無法控制的好方法,如果我們預測迴圈應該執行的次數,就可以安排一個安全計數器進入迴圈,如果迴圈執行次數超過這個安全計數器的值,就強迫離開迴圈,這樣就不會有無窮迴圈的狀況產生了。

.審慎使用 goto 與 continue
在 VB6 的年代,因為沒有 continue 這個指令,所以在迴圈中如果減少迴圈次數,就要使用到 goto,如:

do while not rs.eof
  if NotExpected then goto Continue
  ...
Continue:
  rs.movenext
loop

如果非得使用 goto 請將 continue 的地方放在離迴圈結束最靠近的地方,這樣比較不會出錯。當然用一個 if-then-else Block 也可以做到上述的情況,不一定要使用 goto 來完成。

如果程式語言有提供 continue,那麼將 continue 的情況寫在愈前面,會讓程式的執行效能愈好。例如:

do while not eof(File)
  read(Record, File)
  if (Record.type<>TargetType) then
    continue
  ....
loop

如果是在迴圈的結尾的地方才出現 continue,那不如就不用了。

另外就是前面已經提過的,為迴圈的變數採用有意義的命名,這樣可以讓程式比較容易閱讀與瞭解。

本系列文章


上一篇
程式設計心法:14.流程控制--if & case
下一篇
程式設計心法:16.流程控制--Goto & Return
系列文
程式設計心法31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

0
海綿寶寶
iT邦大神 1 級 ‧ 2009-10-22 09:30:03

現學現練習
請老師評分

&lt;pre class="c" name="code">
do
   改規格
   喝咖啡
   改程式
   吃泡麵
   自己測程式
   睡覺
   使用者測程式
   聽使用者抱怨
until 驗收 or 離職
jamesjan iT邦高手 1 級 ‧ 2009-10-22 13:10:36 檢舉

do 的內容
少了看圖片(誤)...少了自言自語、自 high...XD

jamesjan iT邦高手 1 級 ‧ 2009-10-22 13:13:11 檢舉

蟹老闆一定給 100 分

章魚哥:我還是去睡覺吧

派大星...已經睡著了...XD

fillano iT邦超人 1 級 ‧ 2009-10-22 14:01:34 檢舉

還有上ithelp。

0
fillano
iT邦超人 1 級 ‧ 2009-10-22 09:49:27

如果有iterator可以用,拿來代替迴圈也不錯。或是像ruby的each這類的方法(下一版的javascript陣列也加了forEach方法),都可以避開使用迴圈。不過也許內部實作還是用迴圈實現的也說不定...

我要留言

立即登入留言